import re
import os
from errno import errorcode

import imageio
import pandas as pd
import os
import cv2
import random
import pandas as pd
from PIL import Image

model = dict()
class detectutils:

    def write_xml(mid_path, x_train, x_test):

        train_data_list = []
        # train写成xml文件
        # train_file_list供评估使用
        with open(mid_path + '/train.xml', 'w', encoding='gbk') as file:
            file.write("<dataset>\n")
            file.write("<images>\n")
            for string in x_train:
                file_path = "<image file= '%s'>\n" % (string[0])
                file.write(file_path)
                train_box_list = []
                for box_string in string[1]:
                    box = "<box top=\'%s\' left=\'%s\' width=\'%s\' height=\'%s\'/>\n" % (
                        box_string[0], box_string[1], box_string[2], box_string[3])
                    file.write(box)
                    right = int(box_string[1]) + int(box_string[2])
                    bottom = int(box_string[0]) + int(box_string[3])
                    train_box_list.append([box_string[1], box_string[0], right, bottom])
                file.write("</image>\n")
                train_data_list.append([string[0], train_box_list])
            file.write("</images>\n")
            file.write("</dataset>\n")

        test_data_list = []
        # test数据集写成路径和box的list
        for string in x_test:
            test_box_list = []
            for box_string in string[1]:
                right = int(box_string[1]) + int(box_string[2])
                bottom = int(box_string[0]) + int(box_string[3])
                test_box_list.append([box_string[1], box_string[0], right, bottom])
            test_data_list.append([string[0], test_box_list])

        return mid_path + '/train.xml', pd.DataFrame(train_data_list, columns=['image_path', 'box']), pd.DataFrame(
            test_data_list, columns=['image_path', 'box'])

    def shot_image_data(mid_path, x_train, x_test):
        ###路径不能存在中文名字，非则截图保存失败

        shot_image_path = mid_path + "/images_shot/"
        # 判断是否存在文件夹如果不存在则创建为文件夹
        folder = os.path.exists(shot_image_path)
        if not folder:
            os.makedirs(shot_image_path)  # makedirs 创建文件时如果路径不存在会创建这个路径

        x_train.extend(x_test)
        shot_image_list = []
        for data in x_train:
            img_path = data[0]
            basename = os.path.basename(img_path)
            for temp in data[1]:
                box = temp[0:4]
                lable = temp[4]
                box = list(map(int, box))
                img = cv2.imread(img_path)
                crop = img[box[0]:(box[0] + box[3]), box[1]:(box[1] + box[2])]

                # crop = img[27:45, 67:119]
                if os.path.isfile(shot_image_path + str(basename)):
                    a = str(int(random.uniform(1, 1000)))
                    cv2.imwrite(shot_image_path + a + str(basename), crop)
                    shot_image_list.append([shot_image_path + a + str(basename), lable])
                else:
                    cv2.imwrite(shot_image_path + str(basename), crop)
                    shot_image_list.append([shot_image_path + str(basename), lable])

        return pd.DataFrame(shot_image_list, columns=['file_path', 'lable'])

    def shot(img_path, box):

        box = list(map(int, box))
        img = cv2.imread(img_path)
        crop = img[box[1]:box[3], box[0]:box[2]]
        res = cv2.resize(img, (125, 125)).flatten()
        return res

    def detect_evaluate(data):
        miss_detection = 0
        false_detection = 0
        true_detection = 0
        y_true = dict()
        y_pred = dict()
        for index, row in data.iterrows():
            y_true[os.path.basename(row['image_path'])] = row['box']
            y_pred[os.path.basename(row['image_path'])] = row['box_predict']

        for key in y_true:
            for box_true in y_true[key]:
                true_list = []
                false_list = []
                if key in y_pred.keys():
                    miss_detection += (len(y_true[key]) - len(y_pred[key]))
                    for box_predict in y_pred[key]:
                        ##计算覆盖率
                        x1, y1, x2, y2 = float(box_true[0]), float(box_true[1]), float(box_true[2]), float(box_true[3])
                        x1, x2 = min(x1, x2), max(x1, x2)
                        y1, y2 = min(y1, y2), max(y1, y2)
                        x3, y3, x4, y4 = float(box_predict[0]), float(box_predict[1]), float(box_predict[2]), float(
                            box_predict[3])
                        x3, x4 = min(x3, x4), max(x3, x4)
                        y3, y4 = min(y3, y4), max(y3, y4)
                        if (x2 <= x3 or x4 <= x1) and (y2 <= y3 or y4 <= y1):
                            continue
                        else:
                            lens = min(x2, x4) - max(x1, x3)
                            wide = min(y2, y4) - max(y1, y3)
                            coverage = (lens * wide) / ((x4 - x3) * (y4 - y3))
                            if coverage >= 0.8:
                                if box_true not in true_list:
                                    true_list.append(box_true)
                            else:
                                if box_true not in false_list:
                                    false_list.append(box_true)
                    for true in true_list:
                        try:
                            false_list.remove(true)
                        except Exception as e:
                            continue
                else:
                    miss_detection += len(y_true[key])
                false_detection += len(false_list)
                true_detection += len(true_list)
        print(miss_detection,false_detection,true_detection)
        return miss_detection,false_detection,true_detection